﻿using System.ComponentModel.DataAnnotations;
using System.Net;
using LDM.Framework.ExceptionHandling;
using LDM.Framework.NormalizeActionResult;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using WebApiClientCore.Exceptions;

namespace Microsoft.AspNetCore.Mvc.Filters;

/// <summary>
/// 全局异常 处理
/// </summary>
public class ExceptionFilter : IAsyncExceptionFilter, IOrderedFilter
{
    /// <summary>
    /// 
    /// </summary>
    public int Order => int.MaxValue - 10;

    public Task OnExceptionAsync(ExceptionContext context)
    {
        if (context.ExceptionHandled)
        {
            return Task.CompletedTask;
        }
        var message = Convert(context.Exception);
        context.Result = new JsonResult(ResultData.ValidateError(message, null));
        context.HttpContext.Response.StatusCode = (int)GetStatusCode(context.HttpContext, context.Exception);
        var logger = context.HttpContext.RequestServices.GetService<ILogger<ExceptionFilter>>() ?? NullLogger<ExceptionFilter>.Instance;
        logger!.LogError(context.Exception, message);
        context.ExceptionHandled = true;
        return Task.CompletedTask;
    }

    /// <summary>
    /// 转换异常消息
    /// </summary>
    /// <param name="exception"></param>
    /// <returns></returns>
    private string Convert(Exception exception)
    {
        var message = "发生了未知的内部错误";

        if (exception is BusinessException businessException)
        {
            message = businessException.Message;
        }

        if (exception.InnerException is BusinessException businessInnerException)
        {
            message = businessInnerException.Message;
        }
        if (exception is ValidationException validationException)
        {
            message = validationException.Message ?? "发生了未知的内部错误";
        }
        return message;
    }

    /// <summary>
    /// 获取状态码
    /// </summary>
    /// <param name="httpContext"></param>
    /// <param name="exception"></param>
    /// <returns></returns>
    private HttpStatusCode GetStatusCode(HttpContext httpContext, Exception exception)
    {
        if (exception is ValidationException)
        {
            return HttpStatusCode.BadRequest;
        }

        if (exception is NotImplementedException)
        {
            return HttpStatusCode.NotImplemented;
        }

        if (exception is BusinessException)
        {
            return HttpStatusCode.BadRequest;
        }
        if (exception.InnerException is BusinessException businessException)
        {
            return (HttpStatusCode)businessException.Code;
        }
        //API请求状态码错误
        if (exception.InnerException is ApiResponseStatusException statusException)
        {
            return statusException.StatusCode;
        }
        return HttpStatusCode.InternalServerError;
    }

}
